package com.javasm.gg;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.javasm.commons.base.BaseController;
import com.javasm.commons.entity.AxiosResult;
import com.javasm.commons.entity.CrmProperties;
import com.javasm.commons.entity.TableDatas;
import com.javasm.commons.enums.E;
import com.javasm.commons.exceptions.MvcException;
import com.javasm.commons.util.ServletUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("product")
public class ProductController extends BaseController {
    @Resource
    private ProductService ps;

    @GetMapping("{id}")
    public AxiosResult getProductById(@PathVariable String id){
        Product byId = ps.getById(id);
        return suc(byId);
    }

    @GetMapping
    public AxiosResult getProByPage(Product pro){
        startPage();
        List<Product> proByPage = ps.getProByPage(pro);
        TableDatas t = new TableDatas(proByPage);
        return suc(t);
    }

    @GetMapping("export")
    public ResponseEntity doExport(Product p) throws Exception {
        List<Product> pros = ps.list(new QueryWrapper<>(p));
        HttpServletResponse response = ServletUtils.getResponse();
        response.setHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode("产品列表.xlsx","UTF-8"));
        String target=CrmProperties.getRoot()+"/export";
        File f = new File(target);
        if(!f.exists())f.mkdirs();
        List<String> l = new ArrayList<>();
        l.add("id");
        l.add("createTime");
        l.add("updateTime");
        l.add("errorReason");
        EasyExcel.write(target+"/产品列表.xlsx",Product.class)
                .sheet("产品列表")
                .excludeColumnFieldNames(l)
                .doWrite(()->{
                    return pros;
                });
        byte[] bytes = IoUtil.readBytes(new FileInputStream(target + "/产品列表.xlsx"));
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition","attachment;filename="+ URLEncoder.encode("产品列表.xlsx","UTF-8"));
        return new ResponseEntity(bytes,headers, HttpStatus.OK);
    }

    //数据导入接口
    @PostMapping("uploadExcel")
    public AxiosResult doUpload(MultipartFile excel) throws IOException {
        if (excel==null) throw new MvcException(E.FILE_IS_NULL);
        InputStream inputStream = excel.getInputStream();
        List<Product> errors = new ArrayList<>();//校验错误产品集合
        List<String> allCode = ps.getAllCode();//拿到现有的产品编码

        final int[] allNums = {0};
        final int[] sucNums = {0};

        EasyExcel.read(inputStream, Product.class, new ReadListener<Product>() {
            public static final int BATCH_COUNT = 100;
            private List<Product> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
            @Override
            public void invoke(Product data, AnalysisContext analysisContext) {
                allNums[0]++;
                if (StrUtil.isEmpty(data.getCoding())){
                    data.setErrorReason("产品编码为空");
                    errors.add(data);
                    return;
                }
                if (StrUtil.isEmpty(data.getBrand())){
                    data.setErrorReason("产品品牌为空");
                    errors.add(data);
                    return;
                }
                if (StrUtil.isEmpty(data.getClassify())){
                    data.setErrorReason("产品分类为空");
                    errors.add(data);
                    return;
                }
                if (data.getColor()==null){
                    data.setErrorReason("产品颜色为空");
                    errors.add(data);
                    return;
                }
                boolean contains = allCode.contains(data.getCoding());
                if (contains){
                    data.setErrorReason("产品编码重复");
                    errors.add(data);
                    return;
                }
                allCode.add(data.getCoding());
                cachedDataList.add(data);

                if (cachedDataList.size()>BATCH_COUNT){
                    save();
                    cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
                }
            }
            private void save(){
                boolean b = ps.saveBatch(cachedDataList);
                if (!b) {
                    errors.addAll(cachedDataList);
                    return;
                }
                sucNums[0] = sucNums[0] + cachedDataList.size();
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                save();
            }
        }).sheet().doRead();

        String fileName = "error.xlsx";
        if(errors.size()>0){
            URL resource = this.getClass().getResource("/");
            String path = resource.getPath();
            File dir= new File(path + "/excels/errors");
            if(!dir.exists())dir.mkdirs();

            List<String> l = new ArrayList<>();
            l.add("id");
            l.add("createTime");
            l.add("updateTime");
            EasyExcel.write(dir.getPath()+"/"+fileName,Product.class)
                    .sheet("失败记录")
                    .excludeColumnFieldNames(l)
                    .doWrite(()->{
                        return errors;
                    });
        } else {
            fileName = "";
        }
        Map<String,Object> map = new HashMap<>();
        map.put("allNums",allNums[0]);
        map.put("sucNums",sucNums[0]);
        map.put("errorFile",fileName);
        return suc(map);
    }

    //文件模板下载接口
    @GetMapping("download")
    public ResponseEntity downloadFile(String path) throws Exception {
        File file = ResourceUtils.getFile("classpath:"+path);
        InputStream resourceAsStream =  new FileInputStream(file);
        byte[] bytes = IoUtil.readBytes(resourceAsStream);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Disposition","attachment;filename="+ URLEncoder.encode(file.getName(),"UTF-8"));
        return new ResponseEntity(bytes,headers, HttpStatus.OK);
    }
}
